---
id: api-keys
title: API keys - Temporal Cloud feature guide
sidebar_label: API keys
description: Temporal Cloud supports secure programmatic access through API key authentication, ensuring user-level and RBAC-based authorization. Manage your API keys via Cloud UI or CLI.
slug: /cloud/api-keys
toc_max_heading_level: 4
keywords:
  - explanation
  - feedback
  - get started
  - getting started
  - how to
tags:
  - Temporal Cloud
  - API Keys
  - API
---

:::tip SUPPORT, STABILITY, AND DEPENDENCY INFO

API key authentication for Temporal Cloud, `tcld`, Namespace authentication, SDK-based API calls, and Terraform provider is currently in [Public Preview](/evaluate/development-production-features/release-stages#public-preview).

:::

Temporal Cloud API keys offer industry-standard identity-based authentication for Temporal users and [Service Accounts](/cloud/service-accounts).
This document introduces Temporal Cloud's API key features:

- [API key overview](#overview)
- [API key best practices](#best-practices)
- [Global Administrator and Account Owner API key management](#manage-api-keys)
- [User API key management](#user-api-keys)
- [Manage API keys for Service Accounts](#serviceaccount-api-keys)
- [API keys for Namespace authentication](#namespace-authentication)
- [Use API keys to authenticate](#using-apikeys)
- [Troubleshoot your API key use](#troubleshooting)
- [API keys: Frequently Asked Questions](#faqs)

## API key overview {#overview}

Each Temporal Cloud API key is a unique identity linked to role-based access control (RBAC) settings to ensure secure and appropriate access.

The authentication process follows this pathway:

![API key (authentication) → Identity (user or Service Account) → RBAC (authorization)](/img/apikeyrbac.png)

## API key best practices {#best-practices}

- **Keep it secret; keep it safe**: Treat your API key like a password.
  Do not expose it in client-side code, public repositories, or other easily accessible locations.
- **Rotate keys regularly**: Change your API keys periodically to reduce risks from potential leaks.
  Keys must be rotated every at least every 90 days.
- **Design your code for key updates**: Use key management practices that retrieve your API keys without hard-coding them into your apps.
  This lets you restart your Workers to refresh your rotated keys without recompiling your code.
- **Monitor API key usage**: Check usage metrics and logs regularly.
  Revoke the key immediately if you detect any unexpected or unauthorized activity.
- **Use a Key Management System (KMS)**: Employ a Key Management System to minimize the risk of key leaks.

### API key use cases

API keys are well suited for the following scenarios:

- _**Cloud operations automation**_:
  API keys work with most Temporal Cloud operational tools, including [`tcld`](/cloud/tcld), [Cloud Ops APIs](/ops), and [the Terraform provider](/production-deployment/cloud/terraform-provider).
  Use them to manage your Temporal Cloud account, Namespaces, certificates, and user identities.
  - API keys for Cloud operations tools are in [Public Preview](/evaluate/development-production-features/release-stages#public-preview).
- _**Namespace authentication**_:
  API keys serve as an authentication mechanism for executing and managing Workflows via the SDK and Temporal CLI, offering an alternative to mTLS-based authentication.
  - API keys for Namespace authentication are currently in [Public Preview](/evaluate/development-production-features/release-stages#public-preview).

API keys are an opt-in feature that must be enabled by a Global Administrator or Account Owner.
For instructions on managing API keys for your organization, see [Global Administrator and Account Owner API key management](#manage-api-keys).

### API key permissions

API keys support both users and Service Accounts.
Here are the differences in their permissions:

- Normal users, Global Administrators, and Account Owners can create, delete, and update API key access using the Cloud UI or `tcld`.
- Only Global Administrators and Account Owners can create, delete, and update access to API keys for Service Accounts.

### API key supported tooling

Use API keys to authenticate with:

- [The Temporal CLI v 0.12 or higher](/cli)
- [Temporal SDKs (latest recommended)](/develop)
- [`tcld`](/production-deployment/cloud/tcld/index.mdx)
- [The Cloud Operations API](/production-deployment/cloud/operation-api.mdx)
- [Temporalʼs Terraform provider](/production-deployment/cloud/terraform-provider)

### API key prerequisites

Check these setup details before using API keys:

- The Global Administrator or Account Owner must [enable API keys access](#manage-api-keys) for your Temporal Account.
- Have access to the [Temporal Cloud UI](https://cloud.temporal.io/) or Temporal Cloud CLI ([tcld](https://docs.temporal.io/cloud/tcld/)) to create an API key.

## Global Administrator and Account Owner API key management {#manage-api-keys}

Global Administrators and Account Owners can monitor, manage, disable, and delete API keys for any user or Service Account within their account.
To manage your account’s API keys:

1. [Log in](https://cloud.temporal.io/) to the Temporal Cloud UI.
1. [Select **Settings** and choose **API keys**](https://cloud.temporal.io/settings/api-keys).

:::note ENABLING API KEYS

API keys are not enabled by default.
The Global Administrator or Account Owner must enable access to allow the creation and use of API keys.

:::

Administrators can disable or delete an individual API key using the vertical ellipsis next to the API key row.
Disabling the API keys feature stops the creation of new API keys, but existing API keys can still be used to authenticate into Temporal Cloud until they are either disabled, deleted, or expire.

To find an API key, you can filter by API key state and identity type (Global Administrators and Account Owners only).

:::caution DISABLED API KEYS

Deleting or disabling a key removes its ability to authenticate into Temporal Cloud.
If you delete or disable an API key for a running Workflow, that Workflow will fail until a new API key secret is created and configured.

:::

## User API key management {#user-api-keys}

Manage your personal API keys with the Temporal Cloud UI or `tcld`.
These sections show you how to generate, manage, and remove API keys for a user.

### Generate an API key

Create API keys using one of the following methods:

:::caution

- Once generated, copy and securely save the API key.
  It will be displayed only once for security purposes.
- Temporal supports API keys lifespans up to 90 days.
  Your key will be valid during this period unless it is revoked or the account is deactivated.

:::

#### Generate API keys with the Temporal Cloud UI

[Log in](https://cloud.temporal.io/) to the Temporal Cloud UI and navigate to your [Profile Page → API keys](https://cloud.temporal.io/profile/api-keys).
Then select **Create API key** and provide the following information:

- API key name: a short identifiable name for the key
- API key description: a longer form description of the key's use
- Expiration date: the end-date for the API key (max 90 days)

Finish by selecting **Generate API key**.

#### Generate API keys with tcld

To generate an API key, log into your account and issue the following command:

```command
tcld login
tcld apikey create \
    --name <api-key-name> \
    --description "<api-key-description>" \
    --duration <api-key-duration>
```

Duration specifies the time until the API key expires, for example: "30d", "4d12h", etc.

### Enable or Disable an API Key

You can enable or disable API keys.
When disabled, an API key cannot authenticate with Temporal Cloud.

#### Manage API Key State with the Temporal Cloud UI

Follow these steps:

1. [Log in](https://cloud.temporal.io/) to the Temporal Cloud UI.
1. Go to your [Profile Page → API Keys](https://cloud.temporal.io/profile/api-keys).
1. Select the three vertical dots next to the API key’s row.
1. Choose **Enable** or **Disable**.

#### Manage API Key State with tcld

To manage an API key, log into your account and use one of the following commands to enable or disable it:

```command
tcld login
tcld apikey disable --id <api-key-id>
tcld apikey enable --id <api-key-id>
```

### Delete an API key

Deleting an API key stops it from authenticating with Temporal Cloud.

:::caution

Deleting an API key for a running Workflow will cause it to fail unless you rotate the key with a new one.
This can affect long-running Workflows that outlast the API key's lifetime.

:::

#### Delete API keys with the Temporal Cloud UI

Follow these steps to remove API keys:

1. [Log in](https://cloud.temporal.io/) to the Temporal Cloud UI.
1. Navigate to your [Profile Page → API keys](https://cloud.temporal.io/profile/api-keys).
1. Select the three vertical dots next to the API key's row.
1. Choose **Delete**.

#### Delete API keys with tcld

To delete an API key, log into your account and issue the following:

```command
tcld login
tcld apikey delete --id <api-key-id>
```

### Rotate an API key

Temporal API keys automatically expire.
Their maximum life is 90 days.
Follow these steps to rotate API keys:

1. Create a new key.
   You may reuse key names if that helps.
1. Ensure that both the original key and new key function properly before moving to the next step.
1. Switch clients to load the new key and start using it.
1. Delete the old key after it is no longer in use.

## Manage API keys for Service Accounts {#serviceaccount-api-keys}

Global Administrators and Account Owners can manage API keys for all Service Accounts in their account and generate API keys for Service Accounts.
This is different for users, who generate their own API keys.

### Generate an API Key for a Service Account

Create API keys for Service Accounts using one of the following methods:

:::caution

- Once generated, copy and securely save the API key.
  It will be displayed only once for security purposes.
- Temporal supports API keys with lifespans up to 90 days.
  Your key will be valid during this period unless it is revoked or the account is deactivated.

:::

#### Generate API Keys with the Temporal Cloud UI

[Log in](https://cloud.temporal.io/) to the Temporal Cloud UI and go to [API keys settings](https://cloud.temporal.io/settings/api-keys).
Select **Create API key**, then choose **Service Account** from the "Create an API key for" dropdown.
In the "Mapped to identity" input box, select a Service account and provide the following information:

- **API key name**: A short, identifiable name for the key
- **API key description**: A longer description of the key's use
- **Expiration date**: The end date for the API key (max 90 days)

Finish by selecting **Generate API key**.

#### Generate API keys with tcld

To create an API key for a Service Account, use `tcld apikey create` with the `--service-account-id` flag:

```
tcld apikey create \
    --name <api-key-name> \
    --description "<api-key-description>" \
    --duration <api-key-duration> \
    --service-account-id <service-account-id>
```

### Enable or disable an API key

Global Administrators and Account Owners can manage API key access for any user in their account using the Temporal Cloud UI or `tcld`.

#### Manage keys with Temporal Cloud UI

Follow these steps:

1. Log into Temporal Cloud.
1. Go to [https://cloud.temporal.io/settings/api-keys](https://cloud.temporal.io/settings/api-keys) and find the identity that owns the API key.
1. Click the Disable/Enable button to perform the action.
   There may be a delay after changing the status.
   Once successful, the updated API key status will be shown in the row.

#### Manage keys with tcld

Use the `tcld apikey disable` or `tcld apikey enable` command to disable or enable an API key:

```
tcld login
tcld apikey disable --id <api-key-id>
tcld apikey enable --id <api-key-id>
```

This command is the same for users and Service Accounts.

### Delete an API key for a Service Account

Global Administrators and Account Owners can delete API keys for any user or Service Account in their account using the Temporal Cloud UI or `tcld`.
Deleting a key removes its ability to authenticate with Temporal Cloud.
If you delete an API key for a running Workflow, that Workflow will fail unless you rotate the API key with a new one.

#### Delete a Service Account API key with Temporal Cloud UI

Follow these steps:

1. Navigate to [https://cloud.temporal.io/settings/api-keys](https://cloud.temporal.io/settings/api-keys).
1. Locate the identity that owns the API key and click on the row to view the API keys associated with that identity.
1. Click the Delete button.
   There may be a delay after deleting the API key.
1. Once successful, the updated API key status will be reflected in the row.

#### Delete a Service Account API key with tcld

Use the `tcld apikey delete` command to delete an API key.
The process for deleting an API key is the same for a user or Service Account.

```
tcld login
tcld apikey delete --id <api-key-id>
```

### Rotate a Service Account API key

Temporal API keys automatically expire.
Their maximum life is 90 days.
Follow these steps to rotate API keys:

1. Create a new key.
   You may reuse key names if that helps.
1. Ensure that both the original key and new key function properly before moving to the next step.
1. Switch clients to load the new key and start using it.
1. Delete the old key after it is no longer in use.

## API keys for Namespace authentication {#namespace-authentication}

Create a Namespace with API key authentication as an alternative to mTLS-based authentication by selecting "Allow API key authentication" during setup.
The gRPC endpoint format for the Namespace depends on the authentication method:

- For mTLS connections, use `<namespace>.<account>.tmprl.cloud:7233`.
- For API key connections, use `<region>.<cloud_provider>.api.temporal.io:7233`.

Use this gRPC endpoint in the Temporal CLI or SDK to connect to Temporal Cloud with an API key.

## Use API keys to authenticate {#using-apikeys}

Authenticate with Temporal Cloud using API keys with the following clients:

- [Temporal CLI v0.12 or higher](/cli)
- [SDKs (latest recommended)](/develop)
- [Temporal Cloud CLI `tcld`](/production-deployment/cloud/tcld/index.mdx)
- [The Cloud Operations API](/production-deployment/cloud/operation-api.mdx)
- [Temporal’s Terraform Provider](/production-deployment/cloud/terraform-provider)

### Temporal CLI

To use your API key with the Temporal CLI, either pass it with the `--api-key` flag or set an environment variable (recommended).
The `tcld` tool automatically picks up the `TEMPORAL_CLOUD_API_KEY` environment variable.

```
tcld <command> <subcommand> --api-key YourAPIKey <other flags and options>
```

In addition to the API key, the following client options are required:

- `--address`: Provide the Namespace's gRPC endpoint from the Namespace UI's gRPC endpoint box.
  - For API key connections, use the format `<region>.<cloud_provider>.api.temporal.io:7233`.
  - You can set the address using an environment variable.
- `--namespace`: Provide the `namespace.accountId` from the top of the Namespace page in the UI.
  - Use the format `<namespace_id>.<account_id>`.
  - This can be set using an environment variable.
- `--grpc-meta "temporal-namespace="`: Provide the `namespace.accountId` again as grpc-metadata.
- `--tls`: Use for a secure connection with the appropriate options.
  - This can be set using an environment variable.

For example, to connect to Temporal Cloud from the CLI using an environment variable for the API key:

```bash
export TEMPORAL_API_KEY=<key-secret>
temporal workflow list \
    --address <endpoint> \
    --namespace <namespace_id>.<account_id> \
    --grpc-meta "temporal-namespace=<namespace_id>.<account_id>" \
    --tls
```

### SDK

To use your API key with a Temporal SDK, include the API key in the Bearer token header and specify the Namespace header.
The Bearer token header indicates the authentication type, while the Namespace header routes the request.

**Go SDK (v 1.26.0+)**

Create an initial connection:

```go
clientOptions := client.Options{
    HostPort: <endpoint>,
    Namespace: <namespace_id>.<account_id>,
    ConnectionOptions: client.ConnectionOptions{
        TLS: &tls.Config{},
        DialOptions: []grpc.DialOption{
            grpc.WithUnaryInterceptor(
                func(ctx context.Context, method string, req any, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
                    return invoker(
                        metadata.AppendToOutgoingContext(ctx, "temporal-namespace", <namespace_id>.<account_id>),
                        method,
                        req,
                        reply,
                        cc,
                        opts...,
                    )
                },
            ),
        },
    },
    Credentials: client.NewAPIKeyStaticCredentials(apiKey),
}
c, err := client.Dial(clientOptions)
if err != nil {
  log.Fatalf("error creating temporal client: %v", err)
}
```

Update an API key:

```go
// Assuming client Credentials created with
var myKey string
creds := client.NewAPIKeyDynamicCredentials(
    func(context.Context) (string, error) { return myKey, nil })
// Just update by replacing
myKey = myKeyUpdated
```

#### Go SDK (pre v 1.26.0)

Create an initial connection:

```go
// Create headers provider
type APIKeyProvider struct {
    APIKey string
    Namespace string
}

func (a *APIKeyProvider) GetHeaders(context.Context) (map[string]string, error) {
    return map[string]string{"Authorization": "Bearer " + a.APIKey, "temporal-namespace": a.Namespace}, nil
}

// Use headers provider
apiKeyProvider := &APIKeyProvider{APIKey: <APIKey>, Namespace: <namespace_id>.<account_id>}
c, err := client.Dial(client.Options{
    HostPort: <endpoint>,
    Namespace: <namespace_id>.<account_id>,
    HeadersProvider: apiKeyProvider,
    ConnectionOptions: client.ConnectionOptions{TLS: &tls.Config{
    }},
})
```

Update an API key:

```go
apiKeyProvider.APIKey = myKeyUpdated
```

#### Java SDK

At a client level:

```java
// Create a Metadata object with the Temporal namespace header key.
Metadata.Key<String> TEMPORAL_NAMESPACE_HEADER_KEY =
    Metadata.Key.of("temporal-namespace", Metadata.ASCII_STRING_MARSHALLER);
Metadata metadata = new Metadata();
metadata.put(TEMPORAL_NAMESPACE_HEADER_KEY, <namespace_id>.<account_id>);

// Create the Workflow service stub.
WorkflowServiceStubsOptions.Builder stubOptions =
    WorkflowServiceStubsOptions.newBuilder()
        .setChannelInitializer(
            (channel) -> {
                channel.intercept(MetadataUtils.newAttachHeadersInterceptor(metadata));
            })
        .addGrpcMetadataProvider(
            new AuthorizationGrpcMetadataProvider(() -> "Bearer " + <APIKey>))
        .setTarget(<endpoint>);
stubOptions.setSslContext(SimpleSslContextBuilder.noKeyOrCertChain().setUseInsecureTrustManager(false).build());

WorkflowServiceStubs service = WorkflowServiceStubs.newServiceStubs(stubOptions.build());

/*
 * Get a Workflow service client which can be used to start, Signal, and Query Workflow Executions.
 */
WorkflowClient client =
    WorkflowClient.newInstance(
        service, WorkflowClientOptions.newBuilder().setNamespace(<namespace_id>.<account_id>).build());
```

At a per-call level:

```java
String myKey = "Bearer " + <APIKey>;
WorkflowServiceStubsOptions stubOptions =
    WorkflowServiceStubsOptions.newBuilder()
        .addGrpcMetadataProvider(new AuthorizationGrpcMetadataProvider(() -> myKey))
        .build();

// Just update by replacing, this must be done in a thread safe way
myKey = "Bearer " + <new APIKey>;
```

#### Python SDK (v 1.6.0+)

Create an initial connection:

```python
client = await Client.connect(
    <endpoint>,
    namespace=<namespace_id>.<account_id>,
    rpc_metadata={"temporal-namespace": <namespace_id>.<account_id>},
    api_key=<APIKey>,
    tls=True,
)
```

Update an API key (newer SDK):

```python
my_client.api_key = my_key_updated
```

#### Python SDK (pre v 1.6.0)

Create an initial connection:

```python
client = await Client.connect(
    <endpoint>,
    namespace=<namespace_id>.<account_id>,
    rpc_metadata={"temporal-namespace": <namespace_id>.<account_id>, "Authorization": f"Bearer {<APIKey>}"},
    tls=True,
)
```

Update an API key:

```python
my_client.rpc_metadata = {"Authorization": f"Bearer {<my_key_updated>}"}
```

#### .NET SDK (v 1.1.0+)

Create an initial connection:

```csharp
var myClient = TemporalClient.ConnectAsync(new(<endpoint>)
{
    Namespace = <namespace_id>.<account_id>,
    ApiKey = <APIKey>,
    RpcMetadata = new Dictionary<string, string>()
    {
        ["temporal-namespace"] = "${<namespace_id>.<account_id>}",
    },
    Tls = new(),
});
```

Update an API key:

```csharp
myClient.Connection.ApiKey = myKeyUpdated;
```

**.NET SDK (pre v 1.1.0)**

Create an initial connection:

```csharp
var myClient = TemporalClient.ConnectAsync(new(<endpoint>)
{
    Namespace = <namespace_id>.<account_id>,
    RpcMetadata = new Dictionary<string, string>()
    {
        ["Authorization"] = $"Bearer {<APIKey>}",
        ["temporal-namespace"] = "${<namespace_id>.<account_id>}",
    },
    Tls = new(),
});
```

Update an API key:

```csharp
myClient.Connection.RpcMetadata = new Dictionary<string, string>()
{
    ["Authorization"] = $"Bearer {myKeyUpdated}",
};
```

#### TypeScript SDK (v 1.10.0+)

Create an initial `Connection` (for use with `Client`):

```typescript
const connection = await Connection.connect(
    address: <endpoint>,
    tls: true,
    apiKey: <APIKey>,
    metadata: {
        'temporal-namespace': <namespace_id>.<account_id>,
    },
)
const client = new Client({
    connection,
    namespace: <namespace_id>.<account_id>,
});
```

Create an initial Worker `NativeConnection` (for use with `Worker`):

```typescript
const connection = await NativeConnection.connect(
    address: <endpoint>,
    tls: true,
    apiKey: <APIKey>,
    metadata: {
      'temporal-namespace': <namespace_id>.<account_id>,
    },
)
const worker = await Worker.create({
    connection,
    namespace: <namespace_id>.<account_id>,
    // ...
});
```

Update the API key on an existing `Connection` or `NativeConnection`:

```typescript
connection.setApiKey(<APIKey>);
```

#### TypeScript SDK (pre v 1.10.0)

Create an initial `Connection` (for use with `Client`):

```typescript
const connection = await Connection.connect(
    address: <endpoint>,
    tls: true,
    metadata: {
        'Authorization': `Bearer ${<APIKey>}`,
        'temporal-namespace': <namespace_id>.<account_id>,
    },
)
const client = new Client({
    connection,
    namespace: <namespace_id>.<account_id>,
});
```

Create an initial Worker `NativeConnection` (for use with `Worker`):

```typescript
const connection = await NativeConnection.connect(
    address: <endpoint>,
    tls: true,
    metadata: {
        'Authorization': `Bearer ${<APIKey>}`
        'temporal-namespace': <namespace_id>.<account_id>,
    },
)
const worker = await Worker.create({
    connection,
    namespace: <namespace_id>.<account_id>,
    // ...
});
```

### tcld

To use an API key with `tcld`, choose one of these methods:

- Use the `--api-key` flag.
- Set the `TEMPORAL_CLOUD_API_KEY` environment variable.

### Cloud Ops API

To use an API key with the [Cloud Ops API](/ops), securely pass the API key in your API client.
For a complete example, see [Cloud Samples in Go](https://github.com/temporalio/cloud-samples-go/blob/1dd4254b6ed1937e361005c0144410e72b8a5542/client/api/apikey.go).

### Terraform Provider

To use an API key with the [Temporal Terraform Provider](/production-deployment/cloud/terraform-provider), pass the API key as a provider argument.

## Troubleshoot your API key use {#troubleshooting}

**Invalid API key errors**: Check that you copied the key correctly and that it hasn't been revoked or expired.

## API keys: Frequently Asked Questions {#faqs}

**Q: Can I issue and use multiple API keys for the same account?**

A: Yes, you can generate multiple API keys for different services or team members.

**Q: How many API keys can be issued at once?**

A: Up to 10 active, enabled keys per Identity (user or Service Account).

**Q: Do API keys expire?**

A: Yes, API keys expire after up to 90 days.
Temporal recommends rotating API keys periodically.

**Q: What happens if I misplace or lose my API bearer token/secret key?**

A: The full key is displayed only once upon creation for security reasons.
If you lose it, generate a new one.
